package com.by.component.tencent.sts;

import com.alibaba.fastjson2.JSON;
import com.by.component.tencent.TencentAccessProperties;
import com.tencent.cloud.CosStsClient;
import com.tencent.cloud.Policy;
import com.tencent.cloud.Response;
import com.tencent.cloud.Statement;
import com.tencent.cloud.cos.util.Jackson;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import java.util.TreeMap;

/**
 * 阿里云sts临时访问凭证
 * https://help.aliyun.com/zh/oss/developer-reference/use-temporary-access-credentials-provided-by-sts-to-access-oss?spm=a2c4g.11186623.4.7.600446740vUbNm&scm=20140722.H_100624._.ID_100624-OR_rec-V_1
 *
 * @author YanBingHao
 * @since 2024/1/12
 */
@Slf4j
@Configuration
public class TencentStsSupport {

    @Resource
    private TencentStsProperties tencentStsProperties;

    @Resource
    private TencentAccessProperties tencentAccessProperties;

    /**
     * 创建cos临时密钥
     *
     * @param durationSeconds
     * @param bucket
     * @return
     */
    public Response createCosSts(Long durationSeconds, String bucket) {
        TreeMap<String, Object> config = new TreeMap<>();
        config.put("secretId", tencentAccessProperties.getSecretId());
        config.put("secretKey", tencentAccessProperties.getSecretKey());

        // 临时密钥有效时长，单位是秒
        config.put("durationSeconds", durationSeconds.intValue());
        // 换成你的 bucket
        config.put("bucket", bucket);
        // 换成 bucket 所在地区
        config.put("region", tencentStsProperties.getRegion());

        Statement statement = new Statement();
        statement.setEffect("allow");
        // 密钥的权限列表。简单上传和分片需要以下的权限，其他权限列表请看 https://cloud.tencent.com/document/product/436/31923
        statement.addActions(new String[]{
                //简单上传操作
                "name/cos:PutObject",
                //表单上传对象
                "name/cos:PostObject",
                //分块上传：初始化分块操作
                "name/cos:InitiateMultipartUpload",
                //分块上传：List 进行中的分块上传
                "name/cos:ListMultipartUploads",
                //分块上传：List 已上传分块操作
                "name/cos:ListParts",
                //分块上传：上传分块操作
                "name/cos:UploadPart",
                //分块上传：完成所有分块上传操作
                "name/cos:CompleteMultipartUpload",
                //取消分块上传操作
                "name/cos:AbortMultipartUpload"
        });

        /**
         * 这里改成允许的路径前缀，可以根据自己网站的用户登录态判断允许上传的具体路径
         * 资源表达式规则分对象存储(cos)和数据万象(ci)两种
         * 数据处理、审核相关接口需要授予ci资源权限
         *  cos : qcs::cos:{region}:uid/{appid}:{bucket}/{path}
         *  ci  : qcs::ci:{region}:uid/{appid}:bucket/{bucket}/{path}
         * 列举几种典型的{path}授权场景：
         * 1、允许访问所有对象："*"
         * 2、允许访问指定的对象："a/a1.txt", "b/b1.txt"
         * 3、允许访问指定前缀的对象："a*", "a/*", "b/*"
         *  如果填写了“*”，将允许用户访问所有资源；除非业务需要，否则请按照最小权限原则授予用户相应的访问权限范围。
         *
         * 示例：授权examplebucket-1250000000 bucket目录下的所有资源给cos和ci 授权两条Resource
         */
        statement.addResources(new String[]{"*"});

        Policy policy = new Policy();
        // 把一条 statement 添加到 policy
        // 可以添加多条
        policy.addStatement(statement);
        // 将 Policy 示例转化成 String，可以使用任何 json 转化方式，这里是本 SDK 自带的推荐方式
        config.put("policy", Jackson.toJsonPrettyString(policy));

        Response response = null;
        try {
            response = CosStsClient.getCredential(config);
            log.info("[TencentStsSupport][createCosSts] response:[{}]", response);
        } catch (Exception e) {
            e.printStackTrace();
            throw new IllegalArgumentException("no valid secret !");
        }
        return response;
    }

    public static void main(String[] args) {
        TreeMap<String, Object> config = new TreeMap<>();
        config.put("secretId", "AKIDESvXdks5LIGFf9hGJOUgWLuCeVPUgrCT");
        config.put("secretKey", "IYlrp3FLMPK2qcGlXXSHzcEj8PbjmniX");

        String bucket = "by-resource-test-1324999487";

        // 临时密钥有效时长，单位是秒
        config.put("durationSeconds", 900);
        // 换成你的 bucket
        config.put("bucket", bucket);
        // 换成 bucket 所在地区
        config.put("region", "ap-beijing");

        Statement statement = new Statement();
        statement.setEffect("allow");
        // 密钥的权限列表。简单上传和分片需要以下的权限，其他权限列表请看 https://cloud.tencent.com/document/product/436/31923
        statement.addActions(new String[]{
                //简单上传操作
                "name/cos:PutObject",
                //表单上传对象
                "name/cos:PostObject",
                //分块上传：初始化分块操作
                "name/cos:InitiateMultipartUpload",
                //分块上传：List 进行中的分块上传
                "name/cos:ListMultipartUploads",
                //分块上传：List 已上传分块操作
                "name/cos:ListParts",
                //分块上传：上传分块操作
                "name/cos:UploadPart",
                //分块上传：完成所有分块上传操作
                "name/cos:CompleteMultipartUpload",
                //取消分块上传操作
                "name/cos:AbortMultipartUpload"
        });

        /**
         * 这里改成允许的路径前缀，可以根据自己网站的用户登录态判断允许上传的具体路径
         * 资源表达式规则分对象存储(cos)和数据万象(ci)两种
         * 数据处理、审核相关接口需要授予ci资源权限
         *  cos : qcs::cos:{region}:uid/{appid}:{bucket}/{path}
         *  ci  : qcs::ci:{region}:uid/{appid}:bucket/{bucket}/{path}
         * 列举几种典型的{path}授权场景：
         * 1、允许访问所有对象："*"
         * 2、允许访问指定的对象："a/a1.txt", "b/b1.txt"
         * 3、允许访问指定前缀的对象："a*", "a/*", "b/*"
         *  如果填写了“*”，将允许用户访问所有资源；除非业务需要，否则请按照最小权限原则授予用户相应的访问权限范围。
         *
         * 示例：授权examplebucket-1250000000 bucket目录下的所有资源给cos和ci 授权两条Resource
         */
        statement.addResources(new String[]{"qcs::cos:ap-beijing:uid/1324999487:_BUCKET_/*".replace("_BUCKET_", bucket)});

        Policy policy = new Policy();
        // 把一条 statement 添加到 policy
        // 可以添加多条
        policy.addStatement(statement);
        // 将 Policy 示例转化成 String，可以使用任何 json 转化方式，这里是本 SDK 自带的推荐方式
        config.put("policy", Jackson.toJsonPrettyString(policy));
        System.out.println(JSON.toJSONString(config));
        Response response = null;
        try {
            response = CosStsClient.getCredential(config);
            log.info("[TencentStsSupport][createCosSts] response:[{}]", response);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
